<template>
  <div ref="containerRef" class="lazy-image-container" :style="containerStyle">
    <!-- 占位符 -->
    <div v-if="!loaded" class="lazy-image-placeholder" :style="placeholderStyle">
      <el-icon v-if="showIcon" class="placeholder-icon"><PictureRounded /></el-icon>
    </div>
    
    <!-- 实际图片 -->
    <el-image
      v-show="loaded"
      :src="src"
      :fit="fit"
      :preview-src-list="previewSrcList"
      :initial-index="initialIndex"
      :class="imageClass"
      :style="imageStyle"
      referrerpolicy="no-referrer"
      @error="handleError"
      @load="handleLoad"
    >
      <template #error>
        <div class="image-slot">
          <el-icon><PictureRounded /></el-icon>
          <span>图片加载失败</span>
        </div>
      </template>
    </el-image>
  </div>
</template>

<script>
import { ref, onMounted, onUnmounted, computed, nextTick } from 'vue'
import { PictureRounded } from '@element-plus/icons-vue'

export default {
  name: 'LazyImage',
  components: {
    PictureRounded
  },
  props: {
    src: {
      type: String,
      required: true
    },
    fit: {
      type: String,
      default: 'cover'
    },
    previewSrcList: {
      type: Array,
      default: () => []
    },
    initialIndex: {
      type: Number,
      default: 0
    },
    width: {
      type: [String, Number],
      default: '100%'
    },
    height: {
      type: [String, Number],
      default: '100%'
    },
    placeholderColor: {
      type: String,
      default: '#f0f0f0'
    },
    showIcon: {
      type: Boolean,
      default: true
    },
    rootMargin: {
      type: String,
      default: '50px'
    },
    imageClass: {
      type: String,
      default: ''
    },
    imageStyle: {
      type: Object,
      default: () => ({})
    }
  },
  setup(props) {
    const containerRef = ref(null)
    const loaded = ref(false)
    const error = ref(false)
    let observer = null

    const containerStyle = computed(() => ({
      width: typeof props.width === 'number' ? `${props.width}px` : props.width,
      height: typeof props.height === 'number' ? `${props.height}px` : props.height,
      position: 'relative',
      overflow: 'hidden'
    }))

    const placeholderStyle = computed(() => ({
      width: '100%',
      height: '100%',
      backgroundColor: props.placeholderColor,
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
      minHeight: '100px'
    }))

    const loadImage = () => {
      if (loaded.value) return
      
      const img = new Image()
      img.onload = () => {
        loaded.value = true
        error.value = false
      }
      img.onerror = () => {
        error.value = true
        loaded.value = false
      }
      img.src = props.src
    }

    const handleError = () => {
      error.value = true
      loaded.value = false
    }

    const handleLoad = () => {
      loaded.value = true
      error.value = false
    }

    const setupIntersectionObserver = async () => {
      await nextTick()
      
      // 如果rootMargin为0px，表示立即加载（用于第一张图片）
      if (props.rootMargin === '0px') {
        loadImage()
        return
      }
      
      // 检查浏览器是否支持 Intersection Observer
      if (!('IntersectionObserver' in window)) {
        // 不支持则直接加载
        loadImage()
        return
      }

      if (!containerRef.value) {
        loadImage()
        return
      }

      const options = {
        rootMargin: props.rootMargin,
        threshold: 0.01
      }

      observer = new IntersectionObserver((entries) => {
        entries.forEach(entry => {
          if (entry.isIntersecting) {
            loadImage()
            // 加载后停止观察
            if (observer && containerRef.value) {
              observer.unobserve(containerRef.value)
            }
          }
        })
      }, options)

      // 观察容器元素
      observer.observe(containerRef.value)
    }

    onMounted(() => {
      setupIntersectionObserver()
    })

    onUnmounted(() => {
      if (observer && containerRef.value) {
        observer.unobserve(containerRef.value)
      }
      if (observer) {
        observer.disconnect()
        observer = null
      }
    })

    return {
      containerRef,
      loaded,
      error,
      containerStyle,
      placeholderStyle,
      handleError,
      handleLoad,
      PictureRounded
    }
  }
}
</script>

<style scoped>
.lazy-image-container {
  position: relative;
}

.lazy-image-placeholder {
  position: absolute;
  top: 0;
  left: 0;
  transition: opacity 0.3s ease;
}

.lazy-image-placeholder .placeholder-icon {
  font-size: 48px;
  color: #c0c4cc;
}

.image-slot {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  background-color: #f5f7fa;
  color: #909399;
  font-size: 14px;
}

.image-slot .el-icon {
  font-size: 48px;
  margin-bottom: 8px;
}
</style>

